package showbench

import (
	miner "blockChain/minerNode"
	block "blockChain/singleBlock"
	testbug "blockChain/testBug"
	"os"
	"sync"
)

const MaxChannelSize = 1000

// 设置节点数量totalWorkers，测量区块链的增长速度
func NormalSimulation(totalWorkers int) {
	nodes := make([]*miner.Node, totalWorkers)
	peers := make(map[uint64]chan miner.Message)
	God := make(chan string)

	for i := range nodes {
		peers[uint64(i)] = make(chan miner.Message, MaxChannelSize)
	}
	for i := range nodes {
		nodes[i] = &miner.Node{}
		nodes[i].Initialize(uint64(i), peers, peers[uint64(i)], "000000c", God)
	}

	var wg sync.WaitGroup
	wg.Add(totalWorkers)
	// start all nodes
	for i := range nodes {
		go func(i0 int) {
			nodes[i0].NormalRun()
			wg.Done()
		}(i)
	}

	// 停止所有的矿工节点(按下回车键即可)
	os.Stdin.Read(make([]byte, 1))
	close(God)
	wg.Wait()
}

// 设置一定数量的恶意节点实施分叉攻击
// 诚实节点数量为normalWorkers
// 恶意节点数量为badWorkers
func DivertSimulation(normalWorkers, badWorkers int) {
	prefix5 := make(map[string]block.Block)
	prefix5[testbug.FirstNode.SelfHash] = testbug.FirstNode
	prefix5[testbug.Node2.SelfHash] = testbug.Node2
	prefix5[testbug.Node3.SelfHash] = testbug.Node3
	prefix5[testbug.Node4.SelfHash] = testbug.Node4
	prefix5[testbug.Node5.SelfHash] = testbug.Node5

	prefix3 := make(map[string]block.Block)
	prefix3[testbug.FirstNode.SelfHash] = testbug.FirstNode
	prefix3[testbug.Node2.SelfHash] = testbug.Node2
	prefix3[testbug.Node3.SelfHash] = testbug.Node3

	nodes := make([]*miner.Node, normalWorkers+badWorkers)
	peers := make(map[uint64]chan miner.Message)
	God := make(chan string)
	for i := range nodes {
		peers[uint64(i)] = make(chan miner.Message, MaxChannelSize)
	}

	for i := range nodes {
		nodes[i] = &miner.Node{}
		if i <= normalWorkers-1 {
			nodes[i].InitializeWithPrefix(uint64(i), peers, peers[uint64(i)], "000000c", God, prefix5)
		} else {
			nodes[i].InitializeWithPrefix(uint64(i), peers, peers[uint64(i)], "000000c", God, prefix3)
		}
	}

	var wg sync.WaitGroup
	wg.Add(len(nodes))
	// start all nodes
	for i := range nodes {
		go func(i0 int) {
			if i0 <= normalWorkers-1 {
				nodes[i0].HonestRun()
			} else {
				nodes[i0].DivertRun(badWorkers)
			}
			wg.Done()
		}(i)
	}

	// block to wait for all nodes' threads
	// 停止所有的矿工节点(按下回车键即可)
	os.Stdin.Read(make([]byte, 1))
	close(God)
	wg.Wait()
}
